package com.chatRoom;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.*;

/*
   * JLabel(String text)：创建具有指定文本的 JLabel
   * JTextField()：创建一个默认的文本框
   * JButton()：创建一个无标签文本、无图标的按钮。
   * JTextArea(String text,int rows,int columns)：创建一个既包含指定文本，又包含指定行数和列数的多行文本域
 */

public class GUI_Chat extends JFrame {
    //默认端口
    private static final int DEFAULT_PORT = 8899;
    //显示监听状态
    private JLabel stateLB;
    //显示聊天记录
    private JTextArea centerTestArea;
    //底层面板
    private JPanel southPanel;
    //聊天输入框
    private JTextArea inputTextArea;
    //放置IP地址输入框,按钮
    private JPanel bottomPanel;
    //IP输入框
    private JTextField ipTextFiled;
    //端口号输入框
    private JTextField portTextFiled;
    //发送按钮
    private JButton sendBT;
    //文件发送按钮
    private JButton sendFile;
    //清除聊天记录按钮
    private JButton clearBT;
    //UDP
    private DatagramSocket datagramSocket;

    /*
     * UI
     * 发送端
     * 接收端
     */
    public void setUpUi() {
        //初始化
        setTitle("GUI_CHAT_ROOM");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(450, 450);
        //窗口大小不可调整
        setResizable(false);
        //居中
        setLocationRelativeTo(null);

        //窗口 上 部分
        stateLB = new JLabel("当前还未启动监听...", SwingConstants.CENTER);
        //void setHorizontalAlignment(int alignment)	设置标签内容沿 X 轴的对齐方式
        //stateLB.setHorizontalAlignment((int) JFrame.RIGHT_ALIGNMENT); //右对齐

        //center 部分
        //聊天记录显示区域
        centerTestArea = new JTextArea();
        centerTestArea.setEditable(false); //设置不可编辑
        centerTestArea.setBackground(new Color(211, 211, 211));

        //窗口 下 部分
        //BorderLayout(): 构造一个组件之间没有间距(默认间距为0像素)的新边框布局。
        southPanel = new JPanel(new BorderLayout());
        inputTextArea = new JTextArea(5, 20);
        bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
        ipTextFiled = new JTextField("192.168.0.103", 8);
        portTextFiled = new JTextField(String.valueOf(DEFAULT_PORT), 3);
        sendBT = new JButton("发送消息");
        clearBT = new JButton("清屏");

        //添加组件
        bottomPanel.add(ipTextFiled);
        bottomPanel.add(portTextFiled);
        bottomPanel.add(sendBT);
        bottomPanel.add(clearBT);
        southPanel.add(new JScrollPane(inputTextArea), BorderLayout.CENTER);
        southPanel.add(bottomPanel, BorderLayout.SOUTH);

        add(stateLB, BorderLayout.NORTH);
        add(new JScrollPane(centerTestArea), BorderLayout.CENTER);
        add(southPanel, BorderLayout.SOUTH);
        setVisible(true);
    }

    //发送端
    public void setListener() {
        //为sendBT 按钮添加事件监听器
        sendBT.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取发送目标的IP 和 端口
                final String ipAddress = ipTextFiled.getText();
                final String port = portTextFiled.getText();

                //判断是否为空
                if (ipAddress == null || ipAddress.trim().equals("") ||
                        port == null || port.trim().equals("")) {
                    JOptionPane.showMessageDialog(GUI_Chat.this, "请输入IP地址和端口号");
                    return;
                }

                //获取需要发送的内容
                String sendContent = inputTextArea.getText();
                byte[] buff = sendContent.getBytes();
                try {
                    //将发送的内容显示在聊天记录上
                    centerTestArea.append("我对" + ipAddress + ":" + port +
                            "说：\n" + inputTextArea.getText() + "\n\n");
                    //添加内容后，滚动条自动滚动到最低端
                    centerTestArea.setCaretPosition(centerTestArea.getText().length());
                    //发送数据
                    datagramSocket.send(new DatagramPacket(buff, buff.length,
                            InetAddress.getByName(ipAddress), Integer.parseInt(port)));
                    inputTextArea.setText("");
                } catch (IOException el) {
                    JOptionPane.showMessageDialog(GUI_Chat.this,
                            "出错了，发送不成功");
                    el.printStackTrace();
                }
            }
        });

        //为clearBT按钮添加事件监听器
        clearBT.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                centerTestArea.setText("");
            }
        });
    }

    //接收端
    public void initSocket() {
        while (true) {
            //先关闭
            if (datagramSocket != null && !datagramSocket.isClosed()) {
                datagramSocket.close();
            }
            int port = Integer.parseInt(JOptionPane.showInputDialog(this,
                    "请输入监听的端口号位置", "端口号", JOptionPane.QUESTION_MESSAGE));
            if (port <= 1024 || port > 65535) {
                JOptionPane.showMessageDialog(this, "超出端口范围");
                continue;
            }

            //启动服务端监听
            try {
                datagramSocket = new DatagramSocket(port);
                startListen(); //调用
                stateLB.setText("已在 " + port + " 端口监听");
                break;
            } catch (SocketException e) {
                JOptionPane.showMessageDialog(this, "端口被占用，请重新设置端口");
                stateLB.setText("当前还未启动监听...");
            }
        }
    }

    private void startListen() {
        new Thread() {
            private DatagramPacket packet;

            @Override
            public void run() {
                //如果服务器没有关
                byte[] buff = new byte[64 * 1024];
                packet = new DatagramPacket(buff, buff.length);
                while (!datagramSocket.isClosed()) {
                    try {
                        datagramSocket.receive(packet); //接收消息
                        //添加到聊天记录
                        centerTestArea.append(packet.getAddress().getHostAddress()
                                + ":" + packet.getSocketAddress() + "对我说：\n"
                                + new String(packet.getData(), 0, packet.getLength())
                                + "\n\n");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    //构造函数
    public GUI_Chat() {
        setUpUi();
        initSocket();
        setListener();
    }
}